package com.GatherFour;

import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.wifi.p2p.WifiP2pDevice;
import android.net.wifi.p2p.WifiP2pInfo;
import android.net.wifi.p2p.WifiP2pManager;
import android.net.wifi.p2p.WifiP2pManager.Channel;
import android.net.wifi.p2p.WifiP2pManager.ChannelListener;
import android.net.wifi.p2p.WifiP2pManager.ConnectionInfoListener;
import android.os.Bundle;
import android.widget.TextView;
import android.widget.Toast;

public abstract class WifiDirectManager extends Activity implements ChannelListener, ConnectionInfoListener{
	protected WifiP2pManager manager;
	protected Channel channel;
	protected Player user;
	//private WifiP2pDevice device;
	protected WifiP2pInfo info;
	private BroadcastReceiver receiver = null;
	protected final IntentFilter intentFilter = new IntentFilter();
	protected List<String> clientList = Collections.synchronizedList(new ArrayList<String>());
	protected Context context;
	protected static int ClientID = 1;
	//protected Player[] clients = new Player[3];
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        intentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
        intentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);

        
        initPlayerInfo();
        
        manager = (WifiP2pManager)getSystemService(Context.WIFI_P2P_SERVICE);
        channel = manager.initialize(this, this.getMainLooper(), this);
        if(channel != null){
        	Toast.makeText(WifiDirectManager.this,"Network Initiated",
                    Toast.LENGTH_SHORT).show();
        }
        
        //receiver = new WiFiDirectBroadcastReceiver(manager, channel, this);
		
	
    }
    
    
    @Override
    public void onResume() {
        super.onResume();
        receiver = new WiFiDirectBroadcastReceiver(manager, channel, this);
        registerReceiver(receiver, intentFilter);
    }

    @Override
    public void onPause() {
        super.onPause();
        unregisterReceiver(receiver);

    }
    
    @Override
    protected void onStop() {
        super.onStop();
        //manager.removeGroup(channel, null);
        // The activity is no longer visible (it is now "stopped")
    }
    
    @Override
    public void onDestroy(){
    	super.onDestroy();
    	manager.removeGroup(channel, null);
    }

	@Override
	public void onChannelDisconnected() {
		// TODO Auto-generated method stub
		//manager.removeGroup(channel, null);
        manager = (WifiP2pManager)getSystemService(Context.WIFI_P2P_SERVICE);
        channel = manager.initialize(this, this.getMainLooper(), this);
		
	}
	
	abstract public void updateThisDevice(WifiP2pDevice device);
	
	protected void setDeviceStatus(WifiP2pDevice device, int status){
		device.status = status;
	}
	
	
	protected static String getDeviceStatus(int deviceStatus) {
        switch (deviceStatus) {
            case WifiP2pDevice.AVAILABLE:
                return "Available";
            case WifiP2pDevice.INVITED:
                return "Invited";
            case WifiP2pDevice.CONNECTED:
                return "Connected";
            case WifiP2pDevice.FAILED:
                return "Failed";
            case WifiP2pDevice.UNAVAILABLE:
                return "Unavailable";
            case Player.SERVER:
            	return "Server Available";
            case Player.FULL:
            	return "Full";
            case Player.CLIENT:
            	return "Client";
            default:
                return "Unknown";

        }
    }
	
	@Override
	public void onConnectionInfoAvailable(WifiP2pInfo info) {
		// TODO Auto-generated method stub
		this.info = info;
		TextView view = (TextView) findViewById(R.id.my_name);
        view.setText(info.groupOwnerAddress.getHostAddress());
        view = (TextView) findViewById(R.id.my_status);
        view.setText(info.isGroupOwner?"True":"False");
        
        
        new Thread(new Runnable(){

			@Override
			public void run() {
				// TODO Auto-generated method stub
				try {
					ServerSocket socket = new ServerSocket(8988);
					Socket server = socket.accept();
					
					final String serverAddr = server.getInetAddress().getHostAddress();
					final Scanner sc = new Scanner(server.getInputStream());
					if(sc.hasNextLine()){
						runOnUiThread(new Runnable(){

							@Override
							public void run() {
								// TODO Auto-generated method stub
								TextView view =(TextView) findViewById(R.id.my_status);
								view.setText("address:"+serverAddr);
							}
							
						});
					}else{
						
					}
					
					socket.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
        	
        }).start();
      
	}
	
	
	public void connectGroupOwner(final InetAddress groupOwnerAddress, final String self){
		new Thread(new Runnable(){

			@Override
			public void run() {
				// TODO Auto-generated method stub
				try {
					Socket socket = new Socket(groupOwnerAddress,8988);
					OutputStream out = socket.getOutputStream();
					
					String message = user.name;
					out.write(message.getBytes());
					//TextView view = (TextView)findViewById(R.id.serverStatusID);
					//view.setText("Message Sent.");
					out.close();
					socket.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			
				
			}
			
		}).start();
		Intent myIntent = new Intent(this.getApplicationContext(),GameLobby.class);	
		
		while((clientList.size() == 0)&& self.equals("host")){
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		Bundle bundle = new Bundle();
		if(self.equals("host")){
	//		bundle.putStringArray("address", user.clientAddrs);
			bundle.putInt("clientNum", ClientID-1);
			bundle.putString("clientList", getNameList());
		}
		
		bundle.putString("name", user.name);
		bundle.putString("address", groupOwnerAddress.getHostAddress());
		bundle.putString("self", self);
		myIntent.putExtras(bundle);
		startActivity(myIntent);
	}
	
	public void groupOwnerSetup(final String self){
		 new Thread(new Runnable(){
				
				@Override
				public void run() {
					// TODO Auto-generated method stub
					try {
						ServerSocket socket = new ServerSocket(8988);
						Socket server = socket.accept();
						
						final String targetAddr = server.getInetAddress().getHostAddress();
						
						if(self.equals("host")){
							final Scanner sc = new Scanner(server.getInputStream());
							if(sc.hasNextLine()){
								clientList.add(sc.nextLine());
								ClientID++;
							}
						}
						/*
						final Scanner sc = new Scanner(server.getInputStream());
						if(sc.hasNextLine()){
							runOnUiThread(new Runnable(){
	
								@Override
								public void run() {
									// TODO Auto-generated method stub
									TextView view =(TextView) findViewById(R.id.my_status);
									view.setText("address:"+targetAddr);
								}
								
							});
						}
						*/
						if(self.equals("client")){
							sendPlayerInfoToHost(targetAddr, 8989);
							System.err.println("Player Info Sent to host");
						}
						
						socket.close();
				        Intent myIntent = new Intent(context,GameLobby.class);	
						Bundle bundle = new Bundle();
						if(self.equals("host")){
		//					bundle.putStringArray("address", user.clientAddrs);
							bundle.putInt("clientNum", ClientID-1);
							bundle.putString("clientList", getNameList());
						}
							
						bundle.putString("name", user.name);
						bundle.putString("address", targetAddr);
						
						bundle.putString("self", self);
						myIntent.putExtras(bundle);
						startActivity(myIntent);
						
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
	        	
	        }).start();
	}
	
	public void sendPlayerInfoToHost(final String hostAddr, final int port){
		new Thread(new Runnable(){

			@Override
			public void run() {
				// TODO Auto-generated method stub
				Socket socket;
				try {
					socket = new Socket(hostAddr,port);

					OutputStream out = socket.getOutputStream();
					String message = user.name;
					out.write(message.getBytes());
					//TextView view = (TextView)findViewById(R.id.serverStatusID);
					//view.setText("Message Sent.");
					out.close();
					socket.close();
				} catch (UnknownHostException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

			}
			
		}).start();
	}
	
	public void initPlayerInfo(){
		Bundle bundle = this.getIntent().getExtras();
		user = new Player(bundle.getString("playerName"));
	}

	/*
	public String[] clientsName(){
		String[] result = new String[ClientID-1];
		for(int i = 0; i< ClientID-1 ; i++){
			result[i] = clients[i].name;
		}
			
		return result;
	}

*/
	public String getNameList(){
		String result = "";
		for(int i = 0; i< ClientID-1 ; i++){
			if(i == ClientID-2)
				result = result+clientList.get(i);
			else
				result = result+clientList.get(i)+"|";
		}
			
		return result;
	}
	
}
